package com.codi.api.interceptor;

import com.codi.base.util.EqualsUtil;
import com.codi.bus.constant.GlobalConstant;
import com.codi.bus.core.jwt.Jwt;
import com.codi.bus.core.jwt.TokenState;
import com.codi.bus.exception.BaseException;
import com.codi.message.constant.ErrorConstant;
import com.codi.message.util.MessageUtil;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: zengxl
 * @Description:
 * @Date: 2018/3/12 9:30
 */
@Slf4j
public class H5ValidateInterceptor  implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, String> stringRedisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        String token    = request.getHeader(GlobalConstant.HEADER_AUTH_TOKEN);
        String headUid    = request.getHeader("userid");
        String channelCode    = request.getHeader("channelCode");
        if(StringUtils.isBlank(token) || StringUtils.isBlank(headUid) || StringUtils.isBlank(channelCode)){
            log.error("H5拦截器(H5ValidateInterceptor)：请求头必须包含Auth-Token、userid、channelCode");
            throw new BaseException(ErrorConstant.ERROR_INVALID_REQUEST, "非法请求,请求头缺少必要信息",GlobalConstant.ERROR_TYPE_APPLICATION);
        }
        Map<String, Object> resultMap= Jwt.validToken(token);
        TokenState state=TokenState.getTokenState((String)resultMap.get("state"));
        String redisTokenKey = GlobalConstant.H5 + "_" + channelCode + "_token_" + headUid;
        switch (state) {
            case VALID:
                HashMap<String,String> dataobj =  (HashMap<String,String>) resultMap.get("data");
                String uid = String.valueOf(dataobj.get("uid"));
                if(EqualsUtil.equalsTrim(uid,headUid)) {//检验用户是否匹配
                    String tokenValidate = stringRedisTemplate.opsForValue().get(redisTokenKey);
                    if (StringUtils.isNotEmpty(tokenValidate)) {
                        if(EqualsUtil.equalsTrim(token,tokenValidate)){
                            log.info("H5拦截器(H5ValidateInterceptor)：用户token验证成功:uid="+uid+" token="+token);
                            stringRedisTemplate.boundValueOps(redisTokenKey).expire(GlobalConstant.H5_TOKEN_ACTIVE_TIME, TimeUnit.MILLISECONDS);
                            return true;
                        }else{
                            log.warn("H5拦截器(H5ValidateInterceptor)： 验证TOKEN失败");
                            throw new BaseException(ErrorConstant.ERROR_LOGIN_EXPIRED, "登入过期,重新登入",GlobalConstant.ERROR_TYPE_BUSINESS);
                        }
                    }else{
                        log.warn("H5拦截器(H5ValidateInterceptor)： 验证TOKEN失效");
                        throw new BaseException(ErrorConstant.ERROR_LOGIN_EXPIRED, "登入过期,重新登入",GlobalConstant.ERROR_TYPE_BUSINESS);
                    }
                }else{
                    log.warn("H5拦截器(H5ValidateInterceptor)： 验证TOKEN失败");
                    throw new BaseException(ErrorConstant.ERROR_LOGIN_EXPIRED, "登入过期,重新登入",GlobalConstant.ERROR_TYPE_BUSINESS);
                }
            case EXPIRED:
                String tokenExpiredValidate = stringRedisTemplate.opsForValue().get(redisTokenKey);
                if(StringUtils.isBlank(tokenExpiredValidate)){
                    log.warn("H5拦截器(H5ValidateInterceptor)： 验证TOKEN失效");
                    throw new BaseException(ErrorConstant.ERROR_LOGIN_EXPIRED, "登入过期,重新登入",GlobalConstant.ERROR_TYPE_BUSINESS);
                }else{
                    if(EqualsUtil.equalsTrim(token,tokenExpiredValidate)){
                        log.info("JWT中token检验过期后，H5请求token与数据库token验证成功:uid="+headUid+" 数据库token="+tokenExpiredValidate);
                        stringRedisTemplate.boundValueOps(redisTokenKey).expire(GlobalConstant.H5_TOKEN_ACTIVE_TIME, TimeUnit.MILLISECONDS);
                        return true;
                    }else{
                        log.warn("H5拦截器(H5ValidateInterceptor)： 验证TOKEN失败");
                        throw new BaseException(ErrorConstant.ERROR_LOGIN_EXPIRED, "登入过期,重新登入",GlobalConstant.ERROR_TYPE_BUSINESS);
                    }
                }
            case INVALID:
                log.warn("H5拦截器(H5ValidateInterceptor)： 验证TOKEN失效");
                throw new BaseException(ErrorConstant.ERROR_LOGIN_EXPIRED, "登入过期,重新登入",GlobalConstant.ERROR_TYPE_BUSINESS);
        }
        log.error("H5拦截器(H5ValidateInterceptor)： JWT未识别验证类型:{}",state);
        throw new BaseException(ErrorConstant.ERROR_LOGIN_EXPIRED, "登入过期,重新登入",GlobalConstant.ERROR_TYPE_APPLICATION);
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}
